package org.raymond.iworks.core.utils;

import org.raymond.iworks.apis.vo.CacheVO;
import org.raymond.iworks.commons.constants.CacheConstants;

import java.util.Date;
import java.util.concurrent.ThreadLocalRandom;

public class RedisUtil {
    /**
     * 缓存实际的时间, 比逻辑过期时间要长
     * @param expire
     * @return
     */
    public static long expire(long expire){
        return expire+randomAdditionalExpire(expire);
    }

    public static long expire(long expire, int coefficient){
        return expire*coefficient+randomAdditionalExpire(expire);
    }

    /**
     * 构建缓存对象. 每次取缓存的时候,判断逻辑过期时间是否过期,若已过期,则尝试获取全局锁,然后查数据库,更新缓存,递增版本号.
     * 若未获取到锁,或查询数据库异常,则取缓存对象中的值作为默认值返回,并重新设置实际有效期,但不更新版本号.
     * @param value 缓存对象中真正缓存的值
     * @param expire 逻辑过期时间,根据业务设置
     * @return 缓存对象
     * @param <V> 真正缓存的对象类型
     */
    public static <V> CacheVO<V> cacheVO(V value, long expire, int newVersion){
        Date logicExpireAt = RedisUtil.expireAt(expire);
        CacheVO<V> cacheVO = new CacheVO<>();
        cacheVO.setValue(value);
        cacheVO.setExpire(expire);
        cacheVO.setLogicExpireAt(logicExpireAt);
        cacheVO.setVersion(newVersion);
        return cacheVO;
    }

    private static Date expireAt(long expire){
        Date now = new Date(expire); // 获取时间待优化
        return now;
    }

    private static long randomAdditionalExpire(long expire){
        long randomLimit = CacheConstants.RANDOM_LIMIT;
        if(expire < randomLimit){
            randomLimit = expire;
        }
        return ThreadLocalRandom.current().nextLong(randomLimit);
    }
}
